/**
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { computed, defineComponent, ref, SetupContext, Teleport, watch } from 'vue';
import { ModalButton, ModalProps, modalProps } from './modal.props';
import './modal.css';

export default defineComponent({
    name: 'FModal',
    props: modalProps,
    emits: ['update:modelValue', 'accept', 'cancel'] as (string[] & ThisType<void>) | undefined,
    setup(props: ModalProps, context: SetupContext) {
        const width = ref(props.width);
        const height = ref(props.height);
        const modelValue = ref(props.modelValue);
        const modalId = ref('');
        const customClass = ref(props.class);
        const fitContent = ref(true);
        const showHeader = ref(props.showHeader);
        const headerIconClass = ref('');
        const enableClose = ref(true);
        const enableMaximize = ref(false);
        const enableMinimize = ref(false);
        const dialogType = ref('');
        const iframeSrc = ref('');
        const buttonAlignment = ref('');
        const showButtons = ref(props.showButtons);
        const title = ref(props.title);

        function close($event: MouseEvent, accept: boolean) {
            modelValue.value = false;
            context.emit('update:modelValue', false);
            context.emit(accept ? 'accept' : 'cancel');
        }
        const defaultButtons: ModalButton[] = [
            {
                text: '取消',
                class: 'btn btn-light',
                handle: ($event: MouseEvent) => {
                    close($event, false);
                }
            },
            {
                text: '确定',
                class: 'btn btn-primary',
                handle: ($event: MouseEvent) => {
                    close($event, true);
                }
            }
        ];
        const buttons = ref(props.buttons && props.buttons.length ? props.buttons : defaultButtons);
        const showHeaderIcon = computed(() => !!headerIconClass.value);
        const showFooter = computed(() => !!showButtons.value && !!buttons.value);

        const modalHeaderRef = ref<any>();
        const draggableElementRef = ref<any>();

        watch(
            () => props.modelValue,
            () => {
                modelValue.value = props.modelValue;
            }
        );

        const maximized = ref(false);

        const showModal = computed(() => {
            return modelValue.value;
        });

        const modalContainerClass = computed(() => {
            const classObject = {
                modal: true,
                'farris-modal': true
            } as Record<string, boolean>;
            classObject['f-modal-fitContent'] = fitContent.value;
            return classObject;
        });

        const modalContainerStyle = computed(() => {
            const styleObject = { display: showModal.value ? 'block' : 'none !important' };
            return styleObject;
        });

        const modalDialogClass = computed(() => {
            const classObject = { 'modal-dialog': true };
            const customClassArray = customClass.value.split(' ');
            customClassArray.reduce((target: any, className: string) => {
                target[className] = true;
                return target;
            }, classObject);
            return classObject;
        });

        const modalDialogStyle = computed(() => {
            const styleObject = {
                position: 'absolute' as PositionProperty,
                top: '50%',
                left: '50%',
                width: `${width.value}px`,
                height: fitContent.value ? 'auto' : `${height.value}px`,
                'margin-left': `${0 - width.value / 2}px`,
                'margin-top': fitContent.value ? 'auto' : `${0 - height.value / 2}px`
            };
            return styleObject;
        });

        const modalContentClass = computed(() => {
            const classObject = {
                'modal-content': true,
                'modal-content-has-header': showHeader.value
            };
            return classObject;
        });

        const modalHeaderStyle = computed(() => {
            const styleObject = { display: showHeader.value ? '' : 'none' };
            return styleObject;
        });

        const headerMaxButtonClass = computed(() => {
            const classObject = { 'f-icon': true, modal_maximize: true, modalrevert: maximized.value };
            return classObject;
        });

        const draggableElementStyle = computed(() => {
            const styleObject = { height: '10px', 'z-index': 1, display: showHeader.value ? 'none' : '' };
            return styleObject;
        });

        const modalBodyClass = computed(() => {
            const classObject = { 'modal-body': true, 'f-utils-flex-column': dialogType.value === 'iframe' };
            return classObject;
        });

        function buildFooterStyles(): Record<string, any> {
            return {};
        }

        const modalFooterStyle = computed(() => {
            const styleObject = { textAlgin: buttonAlignment.value };
            const footerSytles = buildFooterStyles();
            return Object.assign(styleObject, footerSytles);
        });

        function changeDialogSize($event: MouseEvent) { }

        return () => {
            return (
                <Teleport to="body">
                    <div class={modalContainerClass.value} style={modalContainerStyle.value}>
                        <div id={modalId.value} class={modalDialogClass.value} style={modalDialogStyle.value}>
                            <div class={modalContentClass.value}>
                                <div ref="modalHeaderRef" class="modal-header" style={modalHeaderStyle.value}>
                                    <div class="modal-title">
                                        {showHeaderIcon.value && <span class={headerIconClass.value} style="margin-right: 8px"></span>}
                                        <span class="modal-title-label">{title.value}</span>
                                    </div>
                                    <div class="actions">
                                        <ul>
                                            {enableMinimize.value && (
                                                <li class="f-btn-icon f-bare">
                                                    <span class="f-icon modal_minimize"></span>
                                                </li>
                                            )}
                                            {enableMaximize.value && (
                                                <li onClick={changeDialogSize} class="f-btn-icon f-bare">
                                                    <span class={headerMaxButtonClass.value}></span>
                                                </li>
                                            )}
                                            {enableClose.value && (
                                                <li class="f-btn-icon f-bare" onClick={(payload: MouseEvent) => close(payload, true)}>
                                                    <span class="f-icon modal_close"></span>
                                                </li>
                                            )}
                                        </ul>
                                    </div>
                                </div>
                                <div ref="dragableElementRef" class="f-utils-absolute-all" style={draggableElementStyle.value}></div>
                                <div class={modalBodyClass.value}>
                                    {context.slots.default?.()}
                                    {dialogType.value === 'iframe' && (
                                        <iframe
                                            title={modalId.value}
                                            class="f-utils-fill"
                                            width="100%"
                                            frameborder="0"
                                            src={iframeSrc.value}></iframe>
                                    )}
                                </div>
                                {showFooter.value && (
                                    <div class="modal-footer" style={modalFooterStyle.value}>
                                        {buttons.value &&
                                            buttons.value.map((button: ModalButton) => {
                                                return (
                                                    <button
                                                        type="button"
                                                        class={button.class}
                                                        onClick={(payload: MouseEvent) => {
                                                            button.handle && button.handle(payload);
                                                        }}>
                                                        {!!button.iconClass && <span class={button.iconClass}>{button.text}</span>}
                                                        {!button.iconClass && <span>{button.text}</span>}
                                                    </button>
                                                );
                                            })}
                                    </div>
                                )}
                            </div>
                        </div>
                    </div>
                </Teleport>
            );
        };
    }
});
